#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include <stdlib.h>
#include "hi_gpio.h"
#include "hi_io.h"
#include "hi_adc.h"
#include "hi_errno.h"
#include "math.h"
#include <errno.h>
#include "wifi_connecter.h"
#include "net_common.h"
#include "iot_watchdog.h"
#include "iot_errno.h"
#include "iot_gpio.h"
#include "iot_uart.h"
#include "iot_gpio_ex.h"
#include "hi_uart.h"


#define SCOUNT 30              // TDS采样次数
#define host "175.178.100.193" // your PC IP address
#define stepPin 7              // 控制引脚
#define dirPin 8               // 方向引脚
#define MAX_TIMEOUTS 3         // udp发送请求最大超时重发次数

#define UART_BUFF_SIZE 14
#define U_SLEEP_TIME 3000000

int state = 1;                // 水阀状态，0：关，1：开；
int water_id = 001;           // 水表ID

const int stepsPerRevolution = 51; // 电机转90°
int num = 0;                       // 水流量脉冲数
float analogBuffer[SCOUNT];        // 将从ADC读取的模拟值存储在数组中
int analogBuffer1[SCOUNT];         // 将从ADC读取的模拟值存储在数组中
float analogBufferTemp[SCOUNT];    // 盗版上一个数组
float analogBufferTemp1[SCOUNT];   // 盗版上一个数组
int analogBufferIndex = 0, analogBufferIndex1 = 0, copyIndex = 0, copyIndex1 = 0;
float averageVoltage = 0, tdsValue = 0, temperature0 = 25, temperature = 0; // 常温，待测温度
float p = 600.0;                                                            // 为1L水所需要的脉冲
float f;                                                                    // 实际水流量
float v;                                                                    // 流速
float Hydraulic;                                                            // 压力
int timeouts = 0;                                                           // 超时重发次数
int flage = 0;                                                              // 开始采样标记，1开始采样
int flage1 = 0;                                                             // 开始上传数据标志
float history_f;                                                            // 历史水流量
//土壤数据
float Humidness,Temperature,PH;   //土壤湿度，土壤温度，土壤PH


int hexToDecimal(char hex1, char hex2)
{
    uint8_t bit;
    uint32_t dec = 0;
    int pow2 = 1;
    // printf("%02X  ", hex1);
    // printf("%02X\n", hex2);
    for (int i = 0; i < 8; i++)
    {
        bit = (hex1 >> i) & 0x01;
        dec += bit * (pow2 << 8 + i);
    }
    // printf("1: %d\n", dec);
    for (int i = 0; i < 8; i++)
    {
        bit = (hex2 >> i) & 0x01;
        dec += bit * (pow2 << i);
    }
    // printf("2: %d\n", dec);
    return dec;
}

void Uart1Config(void)
{
    uint32_t ret;
    /* 初始化UART配置，波特率 9600，数据bit为8,停止位1，奇偶校验为NONE */
    /* Initialize UART configuration, baud rate is 9600, data bit is 8, stop bit is 1, parity is NONE */
    IotUartAttribute uart_attr = {
        .baudRate = 4800,
        .dataBits = 8,
        .stopBits = 1,
        .parity = 0,
    };
    ret = IoTUartInit(HI_UART_IDX_1, &uart_attr);
    if (ret != IOT_SUCCESS)
    {
        printf("Init Uart1 Falied Error No : %d\n", ret);
        return;
    }
}

static void UartTask(void)
{
    const char *data = "\x01\x03\x00\x00\x00\x04\x44\x09";
    unsigned char uartReadBuff1[UART_BUFF_SIZE] = {0};
    uint32_t count = 0;
    uint32_t len = 0;
    const unsigned char uartReadBuff[UART_BUFF_SIZE] = {0};
    float result[4] = {0};

    // 对UART1的一些初始化 Some initialization of UART1
    // 对UART1参数的一些配置 Some configurations of UART1 parameters
    Uart1Config();
    while (1)
    {
        IoTGpioSetOutputVal(IOT_IO_NAME_GPIO_7, 0);                 ////add for bin
        // 通过UART1 发送数据 Send data through UART1
        IoTUartWrite(HI_UART_IDX_1, (unsigned char *)data, 8);
        printf("send data:");
        for (size_t i = 0; i < 8; i++)
        {
            printf("%02X ", (unsigned char)data[i]);
        }
        printf("\n");
        // 通过UART1 接收数据 Receive data through UART1
        len = IoTUartRead(HI_UART_IDX_1, uartReadBuff, UART_BUFF_SIZE);
        // printf("len:%d\n", len);

        if (len > 0)
        {
            // 把接收到的数据打印出来 Print the received data
            // printf("Uart Read Data is: [ %d ] %s \r\n", count, uartReadBuff);
            for (size_t i = 0; i < 13; i++)
            {
                // printf("%02X ", (unsigned char)uartReadBuff[i]);
                // int decimal = hexToDecimal((unsigned char)uartReadBuff[i]);
                uartReadBuff1[i] = (char)uartReadBuff[i];
            }

            int j = 0;
            for (size_t i = 3; i < 11; i = i + 2)
            {
                // printf("test: %02X", uartReadBuff1[i]);
                int decimal = hexToDecimal(uartReadBuff1[i], uartReadBuff1[i + 1]);
                // printf("%d\n", decimal);
                result[j++] = decimal;
            }
            
            Humidness= result[1] / 10.0;
            Temperature=result[2] / 10.0;
            PH=result[3] / 10.0;
            printf("water:%.2f temperature:%.2f elect:%.2f ph:%.2f", result[0] / 10.0, result[1] / 10.0, result[2], result[3] / 10.0);
            printf("\n");
        }
        memset(uartReadBuff1, 0, UART_BUFF_SIZE);
        usleep(U_SLEEP_TIME);
        IoTGpioSetOutputVal(IOT_IO_NAME_GPIO_7, 1);         //add for bin
        count++;
        usleep(U_SLEEP_TIME);                               //add for bin
    }
}

double MYLOG(double a) // 数学中的ln函数
{
    int N = 15; // 我们取了前15+1项来估算
    int k, nk;
    double x, xx, y;
    x = (a - 1) / (a + 1);
    xx = x * x;
    nk = 2 * N + 1;
    y = 1.0 / nk;
    for (k = N; k > 0; k--)
    {
        nk = nk - 2;
        y = 1.0 / nk + xx * y;
    }
    return 2.0 * x * y;
}

void Func() // 中断回调函数测水流量
{
    num++;
}

float getMedianNum(float bArray[], int iFilterLen) // 均值滤波算法
{
    float bTab[iFilterLen];
    for (int i = 0; i < iFilterLen; i++)
        bTab[i] = bArray[i];
    int i, j;
    float bTemp;
    for (j = 0; j < iFilterLen - 1; j++)
    {
        for (i = 0; i < iFilterLen - j - 1; i++)
        {
            if (bTab[i] > bTab[i + 1])
            {
                bTemp = bTab[i];
                bTab[i] = bTab[i + 1];
                bTab[i + 1] = bTemp;
            }
        }
    }
    if ((iFilterLen & 1) > 0)
    {
        bTemp = bTab[(iFilterLen - 1) / 2];
    }
    else
    {
        bTemp = (bTab[iFilterLen / 2] + bTab[iFilterLen / 2 - 1]) / 2;
    }

    return bTemp;
}

void Turn_Off()
{
    if (state == 1)
    {
        printf("now is turn off!\n");
        hi_gpio_set_ouput_val(dirPin, 1);
        for (int x = 0; x < stepsPerRevolution; x++)
        {
            hi_gpio_set_ouput_val(stepPin, 1);
            usleep(2000);
            hi_gpio_set_ouput_val(stepPin, 0);
            usleep(2000);
            // printf("now is step 1\n");
        }
        state = 0;
        printf("turn off down   state: %d\n", state);
    }

    // printf("Turn off down-_-\n");
}

void Turn_On()
{
    if (state == 0)
    {
        printf("now is turn on!\n");
        hi_gpio_set_ouput_val(dirPin, 0);
        for (int x = 0; x < stepsPerRevolution; x++)
        {
            hi_gpio_set_ouput_val(stepPin, 1);
            usleep(2000);
            hi_gpio_set_ouput_val(stepPin, 0);
            usleep(2000);
            // printf("now is step 1\n");
        }
        state = 1;
        printf("turn on down    state: %d\n", state);
    }
    // printf("Turn on down-_-\n");
}


// 上传数据函数
static void WifiConnectTask(void *arg)
{
    (void)arg;
    int ret;
    TCP_WIFI_Init();       // WIFI设置
    usleep(5000000);
    /****  SOCKET    ****/
    struct sockaddr_in server_sock, clinet_sock;
    int sock_fd, client_fd;
    int sin_size;
    if (sock_fd = socket(AF_INET, SOCK_STREAM, 0) == -1)
    {
        printf("socket error\n");
        exit(1);
    }

    bzero(&server_sock, sizeof(server_sock));
    server_sock.sin_family = AF_INET;
    server_sock.sin_addr.s_addr = htonl(INADDR_ANY);
    server_sock.sin_port = htons(TCP_PORT);

    if (bind(sock_fd, (struct sockaddr *)&server_sock, sizeof(struct sockaddr)) == -1)
    {
        printf("bind error\n");
        exit(1);
    }

    if (listen(sock_fd, TCP_BACKLOG) == -1)
    {
        printf("listen error\n");
        exit(1);
    }
    printf("start accept\n");

    while (1)
    {
        sin_size = sizeof(struct sockaddr_in);
        if ((client_fd = accept(sock_fd, (struct sockaddr *)&clinet_sock, (socklen_t *)&sin_size)) == -1)
        {
            printf("accept error\n");
            continue;
        }
        printf("accept success\n");
        while (1)
        {
            //获取指令:
            if ((ret = recv(client_fd, TCP_RX_BUF, BUF_MAX, 0)) <= 0)
            {
                printf("recv error\n");
                break;
            }
            printf("ret=%d,recv:%s\n", ret, TCP_RX_BUF);
            //解析指令
            FSR_ReceiveHandle();
            //上报数据:
            FSR_TransmitHandle();
            send(client_fd, TCP_TX_BUF, strlen(TCP_TX_BUF) + 1, 0);
            usleep(500000);
        }
    }
}

static void AdcGpioTask(void *arg)
{
    (void)arg;

    hi_u16 value;                      // 存温度的
    hi_u16 value1;                     // 存TDS的
    hi_u16 value2;                     // 存水压的
    const float thermistorR = 50000.0; // 温度传感器的分压电阻
    const float T0 = 298.15;           // 热敏电阻在25摄氏度下的温度，单位为开尔文
    const float B = 3950.0;            // 热敏电阻的B值
    float Vntc, Rntc;                  // 热敏电阻的电压、电阻
    float Vtemp;
    int average = 0, sum = 0;
    float date[5];         // 存储数据
    char strArray[20][33]; // 存储转换后的字符串数组包括终止符'\0'

    while (1)
    {
        // 1.测水流量
        printf("-----------start---------\n");
        hi_gpio_register_isr_function(HI_GPIO_IDX_4, HI_INT_TYPE_EDGE, HI_GPIO_EDGE_RISE_LEVEL_HIGH, Func, NULL); // 上升沿中断
        f = (float)num / p;                                                                                       // 用了多少升水
        printf("num:%d\n", num);
        printf("water : %fL\n", f + history_f); // 打印水流量
        date[0] = f + history_f;
        usleep(100000);
        // 2.测温度
        if (hi_adc_read(HI_ADC_CHANNEL_0, &value, HI_ADC_EQU_MODEL_8, HI_ADC_CUR_BAIS_DEFAULT, 0) != HI_ERR_SUCCESS) // 读取引脚的模拟信号
        {
            printf("ADC read error!\n");
        }
        else
        {
            Vntc = ((float)value * 4 * 1.8) / 4096.0; // 将模拟量转换成实际电压值
            // Vntc = Vntc + 1;
            Vtemp = Vntc + 0.1;
            Rntc = (thermistorR * Vtemp) / (5.0 - Vtemp); // 分压公式
            temperature = (1 / (MYLOG((double)Rntc / (double)thermistorR) / B + (1 / T0))) - 273.15; // 热敏电阻计算温度的固定公式
            printf("temp = %.2f\n", temperature);
            date[1] = temperature;
            usleep(100000);
        }

        // 3.测TDS
        if (hi_adc_read(HI_ADC_CHANNEL_4, &value1, HI_ADC_EQU_MODEL_4, HI_ADC_CUR_BAIS_DEFAULT, 0) != HI_ERR_SUCCESS)
        {
            printf("TDS read error!\n");
        }
        else
        {
            // printf("value1:%d\n", value1);
            analogBuffer[analogBufferIndex] = (value1 * 4 * 1.8) / 4096; // 转换成电压
            // averageVoltage = ((float)value1 * 4 * 1.8) / 4096.0;
            // printf("analogBuffer[%d]:%f\n", analogBufferIndex, analogBuffer[analogBufferIndex]);
            analogBufferIndex++;
            if (analogBufferIndex == SCOUNT)
            {
                analogBufferIndex = 0;
            }
            for (copyIndex = 0; copyIndex < SCOUNT; copyIndex++)
            {
                analogBufferTemp[copyIndex] = analogBuffer[copyIndex];
            }
            averageVoltage = getMedianNum(analogBufferTemp, SCOUNT); // 通过中值滤波算法读取更稳定的模拟值，并转换为电压值
            // printf("TDS_averageV1:%.2f\n", ((float)value1 * 4 * 1.8) / 4096.0);
            // averageVoltage = ((float)value1 * 4 * 1.8) / 4096.0;
            // printf("TDS_averageV2:%f\n", averageVoltage);
            tdsValue = (133.42 * averageVoltage * averageVoltage * averageVoltage - 255.86 * averageVoltage * averageVoltage + 857.39 * averageVoltage) * 1.18;
            // ECvalue25  =  ecvalue / (1.0+0.02*(temperature-25.0));
            tdsValue = tdsValue / (1.0 + 0.02 * (22 - 25.0));
            tdsValue = tdsValue / 2;
            printf("TDS:%.2fppm\n", tdsValue);
            date[2] = tdsValue;
            usleep(100000);
        }

        // 4.测水压
        if (hi_adc_read(HI_ADC_CHANNEL_2, &value2, HI_ADC_EQU_MODEL_4, HI_ADC_CUR_BAIS_DEFAULT, 0) != HI_ERR_SUCCESS)
        {
            printf("Hydraulic read error!\n");
        }
        else
        {
            Hydraulic = (value2 * 4 * 1.8) / 4096; // 转换成电压
            // printf("value2:%f", Hydraulic);
            printf("Hydraulic:%.2fKpa\n", (200 * Hydraulic));
            date[3] = 200 * Hydraulic;
            usleep(100000);
        }

        for (int i = 0; i < 4; i++)
        {
            sprintf(strArray[i], "%f", date[i]);
        }

        printf("-----------end---------\n");
        usleep(1000000);
        Turn_Off();
        usleep(4000000);
        Turn_On();
    }
}

static void AdcGpioEntry(void)
{
    printf("ADC Test!\n");
    osThreadAttr_t attr;
    // 水流量计     引脚-GPIO4 SCL
    hi_io_set_func(HI_GPIO_IDX_4, HI_IO_FUNC_GPIO_4_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_4, HI_GPIO_DIR_IN);

    // 温度   引脚-GPIO12     A12
    hi_gpio_init();
    hi_io_set_func(HI_GPIO_IDX_12, HI_IO_FUNC_GPIO_12_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_12, HI_GPIO_DIR_IN);
    // hi_io_set_pull(HI_GPIO_IDX_12, HI_IO_PULL_DOWN); // 下拉

    // hi_io_set_pull(HI_GPIO_IDX_11, HI_IO_PULL_UP); // 上拉

    // TDS          引脚-GPIO9     A111  TX
    hi_io_set_func(HI_GPIO_IDX_9, HI_IO_FUNC_GPIO_9_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_9, HI_GPIO_DIR_IN);

    // 水压          引脚-GPIO5   A5
    hi_io_set_func(HI_GPIO_IDX_5, HI_IO_FUNC_GPIO_5_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_5, HI_GPIO_DIR_IN);

    // 电机   set7-MISO  dir8-MOSI
    // hi_io_set_func(HI_GPIO_IDX_7, HI_IO_FUNC_GPIO_7_GPIO);
    hi_io_set_func(HI_GPIO_IDX_8, HI_IO_FUNC_GPIO_8_GPIO);
    // hi_gpio_set_dir(HI_GPIO_IDX_7, HI_GPIO_DIR_OUT);
    hi_gpio_set_dir(HI_GPIO_IDX_8, HI_GPIO_DIR_OUT);
    // 电机休眠控制引脚  GPIO14  高电平作用，低电平休眠
    hi_io_set_func(HI_GPIO_IDX_14, HI_IO_FUNC_GPIO_14_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_14, HI_GPIO_DIR_OUT);
    hi_gpio_set_ouput_val(HI_GPIO_IDX_14, 1);

    IoTGpioInit(IOT_IO_NAME_GPIO_0);
    // 设置GPIO0的管脚复用关系为UART1_TX Set the pin reuse relationship of GPIO0 to UART1_ TX
    IoSetFunc(IOT_IO_NAME_GPIO_0, IOT_IO_FUNC_GPIO_0_UART1_TXD);
    
    IoTGpioInit(IOT_IO_NAME_GPIO_1);
    // 设置GPIO1的管脚复用关系为UART1_RX Set the pin reuse relationship of GPIO1 to UART1_ RX
    IoSetFunc(IOT_IO_NAME_GPIO_1, IOT_IO_FUNC_GPIO_1_UART1_RXD);

    IoTGpioInit(IOT_IO_NAME_GPIO_7);                                //add for bin
    IoSetFunc(IOT_IO_NAME_GPIO_7, IOT_IO_FUNC_GPIO_7_GPIO);         //add for bin
    IoTGpioSetDir(IOT_IO_NAME_GPIO_7, IOT_GPIO_DIR_OUT);            //add for bin

    attr.name = "AdcGpioTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 30720;
    attr.priority = 25;

    if (osThreadNew(AdcGpioTask, NULL, &attr) == NULL)
    {
        printf("[LedExample] Falied to create LedTask!\n");
    }

    attr.name = "UART";
    attr.priority = 24;
    if (osThreadNew((osThreadFunc_t)UartTask, NULL, &attr) == NULL)
    {
        printf("[UartTask] Failed to create UartTask!\n");
    }

    attr.name = "WifiConnectTask";
    attr.priority = 24;
    if (osThreadNew((osThreadFunc_t)WifiConnectTask, NULL, &attr) == NULL)
    {
        printf("[WifiConnectTask] Failed to create UartTask!\n");
    }
}

SYS_RUN(AdcGpioEntry);